package sys;

import java.util.*;
import java.sql.*;
import java.io.*;
import java.util.concurrent.*;

import sys.fsm.*;
import sys.transport.*;
import sys.logic.*;
import sys.message.*;
import sys.database.*;
import org.json.*;
import sys.utils.*;

public class RequestManager
{
    public RequestManager(String confFilePath)
    {
        readParams(confFilePath);
        
        db = new DBWrapper(DBServer, DB, DBUser, DBPass);
        db.connect();

        try { nextRequestNumber = SysaDatabase.maxRequestID(DBServer, DB, DBUser, DBPass) + 1; }
        catch(SQLException e) { System.out.println("Error when retrieving MAX(ID) : " + e.getMessage()); };

        requests = new Hashtable<Integer, Automat>();
    }

    private void readParams(String confFilePath)
    {
        File confFile = new File(confFilePath);
        String conf = ReadWriteTextFile.getContents(confFile);

        try
        {
            JSONObject jo = new JSONObject(conf);

            mailserver = jo.getString("mailserver");
            portPOP3 = jo.getString("pop3port");
            maillogin = jo.getString("maillogin");
            mailpass = jo.getString("mailpass");

            DBServer = jo.getString("DBServer");
            DB = jo.getString("DB");
            DBUser = jo.getString("DBUser");
            DBPass = jo.getString("DBPass");

            automatConfFilePath = jo.getString("automatConfFilePath"); 

            mailboxCheckingInterval = jo.getInt("mailboxCheckingInterval");
        }
        catch(JSONException e)
        {
            System.out.println("Receiver : Error while parsing config file : " + e.getMessage());
        }

    }

    public void start()
    {
        MessageReceiver mr = new MessageReceiverPOP3(mailserver, portPOP3, maillogin, mailpass);
        MessageCheckerClient mcc = new MailsEntryPoint();
        mc = new MessageChecker(mr, mcc, mailboxCheckingInterval);
        mc.start();
    }

    public void stop()
    {
        mc.stop();
    }
    
    public Automat getAutomat(int id)
    {
        return requests.get(id);
    }

    class MailsEntryPoint implements MessageCheckerClient
    {
        public void newMessages(ConcurrentLinkedQueue<UniMessage> messages)
        {
            System.out.println("Systema have got a message");
            for (UniMessage m : messages)
            {
                System.out.println("FROM: " + m.getFrom() + ", TO: " + m.getTo() + ", BODY: " + m.getBody());
            
                String type = null;
                try
                {
                    type = m.getString("Type");
                }
                catch(Exception e)
                {
                    System.out.println("Error when retrieving field 'Type' : " + e.getMessage());
                    continue;
                }

                if (type.compareTo("newRequest") == 0)
                {
                    System.out.println("Creating a new request");

                    try
                    {
                        String PSAddress = m.getString("PayingSystem");
                        String userName = m.getString("UserName");
                        int quantity = m.getInt("Quantity");
                        requests.put(nextRequestNumber, new Automat(0, automatConfFilePath)); 
                        requests.get(nextRequestNumber).start_Message(nextRequestNumber, PSAddress, userName, quantity);
                    }
                    catch(Exception e) {System.out.println("Error when retiriving fields from 'NewRequest' : " + e.getMessage());};
                    
                    nextRequestNumber++;
                }
                else if (type.compareTo("ackSeller1") == 0)
                {
                    System.out.println("First ack from seller");

                    try
                    {
                        int ackOnId = m.getInt("ackOn");
                        try {requests.get(ackOnId).ack_Seller_1_Message();}
                        catch (Exception e) { System.out.println("Error : " + e.getMessage()); }
                    }
                    catch(Exception e) {System.out.println("Error when retiriving fields from 'ackSeller1' : " + e.getMessage());};
                }
                else if (type.compareTo("ackPayingSystem") == 0)
                {
                    System.out.println("Ack from paying system");

                    try
                    {
                        int ackOnId = m.getInt("ackOn");
                        try {requests.get(ackOnId).ack_PayingSystem_1_Message(); }
                        catch (Exception e) { System.out.println("Error : " + e.getMessage()); }
                    }
                    catch(Exception e) {System.out.println("Error when retiriving fields from 'ackPayingSystem' : " + e.getMessage());};
                }
                else if (type.compareTo("ackUser") == 0)
                {
                    System.out.println("Ack from user");

                    try
                    {
                        int ackOnId = m.getInt("ackOn");
                        requests.get(ackOnId).ack_User_1_Message();
                    }
                    catch (Exception e) { System.out.println("Error : " + e.getMessage()); }
                }
                else if (type.compareTo("ackSeller2") == 0)
                {
                    System.out.println("Second ack from seller");

                    try
                    {
                        int ackOnId = m.getInt("ackOn");
                        try { requests.get(ackOnId).ack_Seller_2_Message(); }
                        catch (Exception e) { System.out.println("Error : " + e.getMessage()); }
                    }
                    catch(Exception e) {System.out.println("Error when retiriving fields from 'ackSeller2' : " + e.getMessage());};
                }
                else if (type.compareTo("nackSeller1") == 0)
                {
                    System.out.println("Nack from seller");

                    try
                    {
                        int nackOnId = m.getInt("nackOn");
                        try { requests.get(nackOnId).nack_Seller_1_Message(); }
                        catch (Exception e) { System.out.println("Error : " + e.getMessage()); }
                    }
                    catch(Exception e) {System.out.println("Error when retiriving fields from 'nackSeller1' : " + e.getMessage());};
                }
                else if (type.compareTo("nackUser") == 0)
                {
                    System.out.println("Nack from user");

                    try
                    {
                        int nackOnId = m.getInt("nackOn");
                        try {requests.get(nackOnId).nack_User_1_Message(); }
                        catch (Exception e) { System.out.println("Error : " + e.getMessage()); }
                    }
                    catch(Exception e) {System.out.println("Error when retiriving fields from 'nackUser1' : " + e.getMessage());};
                }
                else
                {
                    System.out.println("Unknown type. Skipping.");
                }
            }
        }
    }

    // Parametrs
    private String mailserver, portPOP3, maillogin, mailpass;
    private String DBServer, DB, DBUser, DBPass;
    long mailboxCheckingInterval;
    String automatConfFilePath;

    MessageChecker mc;
    private DBWrapper db;
    private Hashtable<Integer, Automat> requests;
    private int nextRequestNumber;
}
